/**
 * Alibaba.com.cn Inc.
 * Copyright (c) 2004-2021 All Rights Reserved.
 */
package com.yongbao.common.aspect;

import com.yongbao.common.Constants;
import com.yongbao.common.annotation.WebAccess;
import com.yongbao.common.enums.ErrorCode;
import com.yongbao.common.enums.TerminalEnum;
import com.yongbao.common.exception.BusinessException;
import com.yongbao.common.service.RedisService;
import com.yongbao.context.BaseSession;
import com.yongbao.context.SessionContext;
import com.yongbao.mapper.UserMapper;
import com.yongbao.model.domain.UserDO;
import com.yongbao.model.vo.UserVO;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

/**
 * @author zhanghong
 * @version SessionAspect.java, v 0.1 2023/6/22 21:32 下午 SessionAspect Exp $$
 */
@Component
@Aspect
@Order(1)
@Slf4j
public class SessionAspect {

    @Autowired
    private RedisService redisService;
    @Autowired
    private UserMapper userMapper;

    @Pointcut("execution(* com.yongbao..*Controller.*(..))")
    public void executionService() {
    }

    @Around("executionService()")
    public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
        // 获取方法的签名
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        // 获取方法@WebAccess注解
        WebAccess webAccess = methodSignature.getMethod().getAnnotation(WebAccess.class);
        // 没有方法注解，获取类@WebAccess注解a
        if (webAccess == null) {
            Class clazz = joinPoint.getTarget().getClass();
            webAccess = (WebAccess) clazz.getAnnotation(WebAccess.class);
        }
        // @WebAccess注解为空，直接放行
        if (webAccess == null || !webAccess.login()) {
            return joinPoint.proceed();
        }

        if (SessionContext.context.get() == null) {
            throw new BusinessException(ErrorCode.NOT_LOGIN, "登录状态已失效，请重新登录。");
        }

        TerminalEnum terminalEnum = SessionContext.context.get().getTerminalEnum();
        if (terminalEnum == TerminalEnum.PC) {
            // 否则，从登录态获取用户信息
            Long loginAccountId = SessionContext.getAdminUserId();
            // 用户信息为空，说明用户未登录，抛出异常
            if (loginAccountId == null) {
                throw new BusinessException(ErrorCode.NOT_LOGIN, "登录状态已失效，请重新登录。");
            }
            // todo 如果要检验是否禁用后期可以在这个地方进行校验
        } else if (terminalEnum == TerminalEnum.WECHAT) {
            String token = SessionContext.context.get().getToken();
            UserVO userVO = redisService.getKey(String.format(Constants.LOGIN_USER_RDB_PREFIX, token), UserVO.class);
            if (userVO == null) {
                throw new BusinessException(ErrorCode.NOT_LOGIN, "登录状态已失效，请重新登录。");
            }
            UserDO userDO = userMapper.selectDOById(userVO.getId());
            if (userDO == null) {
                throw new BusinessException(ErrorCode.NOT_LOGIN, "登录状态已失效，请重新登录。");
            }

            SessionContext.context.set(BaseSession.builder().userVO(userVO).terminalEnum(terminalEnum).build());
        }

        // 用户信息存在，放行
        return joinPoint.proceed();
    }
}
